//	template<class Classifier, class Params>
//	static Mat runGeneticAlgorithm(const int numberOfElements,
//									   const int numberOfAttributes,
//									   const int numberOfIterations,
//									   const float percentOfLeaders,
//									   const float percentOfMutants,
//									   const Mat& data,
//									   const Mat& labels,
//									   Classifier classifier,
//									   Params params,
//									   int k)
//	{
//		//Initialize
//		srand(time(NULL));
//		vector<KeySort> elements = initializeElements(numberOfElements, numberOfAttributes);
//		vector<KeySort> newElements = initializeElements(numberOfElements, numberOfAttributes);
//
//		for (int N = 0; N < numberOfIterations; N++)
//		{
//			elements = crossOverAll(newElements,numberOfElements,numberOfAttributes,percentOfLeaders,percentOfMutants);
//			for (int i = 0; i < numberOfElements; i++)
//			{
//				Mat currData = createDataMat(elements,i, data);
//
//				//Aqui pode-se copiar diretamente Mat currLabels = getLabels;
//				Mat currLabels = createLabelsMat(elements,i,labels);
//				//Mat currLabels = labels.clone();
//
//				cout << currLabels << endl;
//				cout << currData << endl;
//				classifier.train(currData, currLabels, params);
//
//				//attribute current data to new Elements
//				Mat conf = conf_matrix<Classifier, Params>(classifier, params, currData, currLabels, k);
//				/*newElements[i].key = getROCevaluation<Classifier, Params>(currData, currLabels,classifier, params,k);*/
//				newElements[i].key = ROC(conf);
//				newElements[i].element = elements[i].element.clone();
//				cout << newElements[i].key << endl;
//			}
//			//std::sort(newElements.begin(), newElements.end());
//			//std::reverse(newElements.begin(), newElements.end());
//
//			//for (int i = 0; i < newElements.size(); i++)
//			//{
//			//	cout << newElements[i].key << endl;
//			//}
//		
//			vector<KeySort> tempElements = newElements;
//
//			std::sort(tempElements.begin(), tempElements.end());
//			std::reverse(tempElements.begin(), tempElements.end());
//			//cout << "ORDENADO" << endl;
//			//for (int i = 0; i < tempElements.size(); i++)
//			//{
//			//	cout << tempElements[i].key << endl;
//			//}
//
//			//elements = newElements;
//
//			cout << ((float)N/(float)numberOfIterations) * 100 << " %" << endl;
//			cout << "BEST Youden " << tempElements[0].key << endl;
//		}
//		std::sort(elements.begin(), elements.end());
//		std::reverse(elements.begin(), elements.end());
//		cout << elements[0].element << endl;
//		cout <<  elements[0].key << endl;
//		return elements[0].element;
//	}
//
//	static vector<KeySort> initializeVector(int n, int numOfAtt)
//	{
//		vector<KeySort> v;
//		for (int i = 0; i < n ; i++)
//		{
//			v.push_back(KeySort(numOfAtt));
//		}
//		return v;
//	}
//
//	static vector<KeySort> initializeElements(int numberOfElements, int numberOfAttributes)
//	{
//		vector<KeySort> elements = initializeVector(numberOfElements, numberOfAttributes);
//		for (int i = 0; i < numberOfElements; i++)
//		{
//			for (int j = 0; j < numberOfAttributes; j++)
//			{
//				elements[i].key = 0;
//				elements[i].element.at<int>(0,j) = (rand() % 2);
//			}
//		}
//		return elements;
//	}
//
//	static Mat createDataMat(vector<KeySort> d, int n, const Mat& data)
//	{
//		int count = countNumberOfAttributes(d[n].element);
//		Mat_<float> curr( data.rows, count);
//
//		for (int i = 0; i < data.rows; i++)
//		{
//			int inc = 0;
//			for (int j = 0; j < data.cols; j++)
//			{
//				if (d[n].element.at<int>(0,j) == 1)
//				{
//					curr.at<float>(i,inc++) = data.at<float>(i,j);
//				}
//			}
//		}
//		return curr;
//	}
//
//	static Mat createLabelsMat(vector<KeySort> data, int n, const Mat& labels)
//	{
//		Mat_<float> curr( labels.rows, 1);
//		for (int i = 0; i < labels.rows; i++)
//		{
//			curr.at<float>(i,0) = labels.at<float>(i,0);
//		}
//		return curr;
//	}
//
//	static vector<KeySort> crossOverAll(vector<KeySort> elems, int numberOfElements, int numberOfAttributes, float percentOfLeaders, float percentOfMutants)
//	{
//		vector<KeySort> ret = initializeElements(numberOfElements, numberOfAttributes);
//
//		std::sort(elems.begin(), elems.end());
//		std::reverse(elems.begin(), elems.end());
//
//		int bests = (percentOfLeaders/100.f) * elems.size();
//
//		for (int i = 0; i < bests; i++)
//		{
//			ret[i].key = elems[i].key;
//			ret[i].element = elems[i].element.clone();
//		}
//
//		//std::random_shuffle(elems.begin(), elems.end());
//		for (int i = 0; i < elems.size()-bests; i = i + 2)
//		{
//			Mat child1;
//			Mat child2;
//			crossOver(elems[i].element, elems[i+1].element, child1, child2);
//			if (i+bests+1 < elems.size())
//			{
//				ret[i+bests].element = child1.clone();
//				ret[i+bests+1].element = child2.clone();
//			}
//
//		}
//
//		int mutation = percentOfMutants/100.f * elems.size();
//		for (int i = 0 ; i < mutation; i++)
//		{
//			int randElement = rand() % elems.size();
//			int randAttribute = rand() % elems[0].element.cols;
//			if ( ret[randElement].element.at<int>(0,randAttribute) == 0)
//			{
//				ret[randElement].element.at<int>(0,randAttribute) = 1;
//			}
//			else
//			{
//				ret[randElement].element.at<int>(0,randAttribute) = 0;
//			}
//		}
//		return ret;
//	}
//
//	static void crossOver(const Mat& parent1, const Mat& parent2, Mat& child1, Mat& child2)
//	{
//		int random = rand() % parent1.cols;
//		child1 = Mat_<int>(1,parent1.cols);
//		child2 = Mat_<int>(1,parent1.cols);
//
//		for (int i = 0; i < random; i++)
//		{
//			child1.at<int>(0,i) = parent1.at<int>(0,i);
//			child2.at<int>(0,i) = parent2.at<int>(0,i);
//		}
//		for (int i = random; i < parent1.cols; i++)
//		{
//			child2.at<int>(0,i) = parent1.at<int>(0,i);
//			child1.at<int>(0,i) = parent2.at<int>(0,i);
//		}
//	}
//
//	static int countNumberOfAttributes(Mat d)
//	{
//		int cnt = 0;
//		for (int i = 0; i < d.cols; i++)
//		{
//			if (d.at<int>(0,i) == 1)
//			{
//				cnt++;
//			}
//		}
//		return cnt;
//	}
//
//	template<class Classifier, class Params>
//	static float getROCevaluation(const Mat& d, const Mat& l, Classifier classifier, Params params, int k)
//	{
//		//Mat conf = conf_matrix<Classifier, Params>(classifier, params, d, l, k);
//		//cout << conf << endl;
//		//float temp = ROC(conf);
//		//conf.f
//		return conf_matrix<Classifier, Params>(classifier, params, d, l, k);
//	}


	
	//static Mat runGeneticAlgorithm(const int numberOfElements,
	//								   const int numberOfAttributes,
	//								   const int numberOfIterations,
	//								   const float percentOfLeaders,
	//								   const float percentOfMutants,
	//								   const Mat& data,
	//								   const Mat& labels,
	//								   CvSVM classifier,
	//								   CvSVMParams params,
	//								   int k)
	//{
	//	//Initialize
	//	srand(time(NULL));
	//	vector<KeySort> elements = initializeElements(numberOfElements, numberOfAttributes);
	//	vector<KeySort> newElements = initializeElements(numberOfElements, numberOfAttributes);

	//	for (int N = 0; N < numberOfIterations; N++)
	//	{
	//		elements = crossOverAll(newElements,numberOfElements,numberOfAttributes,percentOfLeaders,percentOfMutants);
	//		for (int i = 0; i < numberOfElements; i++)
	//		{
	//			Mat currData = createDataMat(elements,i, data);

	//			//Aqui pode-se copiar diretamente Mat currLabels = getLabels;
	//			Mat currLabels = createLabelsMat(elements,i,labels);
	//			//Mat currLabels = labels.clone();

	//			cout << currLabels << endl;
	//			cout << currData << endl;
	//			classifier.train(currData, currLabels, Mat(), Mat(), params);

	//			//attribute current data to new Elements
	//			Mat conf = conf_matrix(classifier, params, currData, currLabels, k);
	//			/*newElements[i].key = getROCevaluation<Classifier, Params>(currData, currLabels,classifier, params,k);*/
	//			newElements[i].key = ROC(conf);
	//			newElements[i].element = elements[i].element.clone();
	//			cout << newElements[i].key << endl;
	//		}
	//		//std::sort(newElements.begin(), newElements.end());
	//		//std::reverse(newElements.begin(), newElements.end());

	//		//for (int i = 0; i < newElements.size(); i++)
	//		//{
	//		//	cout << newElements[i].key << endl;
	//		//}
	//	
	//		vector<KeySort> tempElements = newElements;

	//		std::sort(tempElements.begin(), tempElements.end());
	//		std::reverse(tempElements.begin(), tempElements.end());
	//		//cout << "ORDENADO" << endl;
	//		//for (int i = 0; i < tempElements.size(); i++)
	//		//{
	//		//	cout << tempElements[i].key << endl;
	//		//}

	//		//elements = newElements;

	//		cout << ((float)N/(float)numberOfIterations) * 100 << " %" << endl;
	//		cout << "BEST Youden " << tempElements[0].key << endl;
	//	}
	//	std::sort(elements.begin(), elements.end());
	//	std::reverse(elements.begin(), elements.end());
	//	cout << elements[0].element << endl;
	//	cout <<  elements[0].key << endl;
	//	return elements[0].element;
	//}

	//static vector<KeySort> initializeVector(int n, int numOfAtt)
	//{
	//	vector<KeySort> v;
	//	for (int i = 0; i < n ; i++)
	//	{
	//		v.push_back(KeySort(numOfAtt));
	//	}
	//	return v;
	//}

	//static vector<KeySort> initializeElements(int numberOfElements, int numberOfAttributes)
	//{
	//	vector<KeySort> elements = initializeVector(numberOfElements, numberOfAttributes);
	//	for (int i = 0; i < numberOfElements; i++)
	//	{
	//		for (int j = 0; j < numberOfAttributes; j++)
	//		{
	//			elements[i].key = 0;
	//			elements[i].element.at<int>(0,j) = (rand() % 2);
	//		}
	//	}
	//	return elements;
	//}

	//static Mat createDataMat(vector<KeySort> d, int n, const Mat& data)
	//{
	//	int count = countNumberOfAttributes(d[n].element);
	//	Mat_<float> curr( data.rows, count);

	//	for (int i = 0; i < data.rows; i++)
	//	{
	//		int inc = 0;
	//		for (int j = 0; j < data.cols; j++)
	//		{
	//			if (d[n].element.at<int>(0,j) == 1)
	//			{
	//				curr.at<float>(i,inc++) = data.at<float>(i,j);
	//			}
	//		}
	//	}
	//	return curr;
	//}

	//static Mat createLabelsMat(vector<KeySort> data, int n, const Mat& labels)
	//{
	//	Mat_<float> curr( labels.rows, 1);
	//	for (int i = 0; i < labels.rows; i++)
	//	{
	//		curr.at<float>(i,0) = labels.at<float>(i,0);
	//	}
	//	return curr;
	//}

	//static vector<KeySort> crossOverAll(vector<KeySort> elems, int numberOfElements, int numberOfAttributes, float percentOfLeaders, float percentOfMutants)
	//{
	//	vector<KeySort> ret = initializeElements(numberOfElements, numberOfAttributes);

	//	std::sort(elems.begin(), elems.end());
	//	std::reverse(elems.begin(), elems.end());

	//	int bests = (percentOfLeaders/100.f) * elems.size();

	//	for (int i = 0; i < bests; i++)
	//	{
	//		ret[i].key = elems[i].key;
	//		ret[i].element = elems[i].element.clone();
	//	}

	//	//std::random_shuffle(elems.begin(), elems.end());
	//	for (int i = 0; i < elems.size()-bests; i = i + 2)
	//	{
	//		Mat child1;
	//		Mat child2;
	//		crossOver(elems[i].element, elems[i+1].element, child1, child2);
	//		if (i+bests+1 < elems.size())
	//		{
	//			ret[i+bests].element = child1.clone();
	//			ret[i+bests+1].element = child2.clone();
	//		}

	//	}

	//	int mutation = percentOfMutants/100.f * elems.size();
	//	for (int i = 0 ; i < mutation; i++)
	//	{
	//		int randElement = rand() % elems.size();
	//		int randAttribute = rand() % elems[0].element.cols;
	//		if ( ret[randElement].element.at<int>(0,randAttribute) == 0)
	//		{
	//			ret[randElement].element.at<int>(0,randAttribute) = 1;
	//		}
	//		else
	//		{
	//			ret[randElement].element.at<int>(0,randAttribute) = 0;
	//		}
	//	}
	//	return ret;
	//}

	//static void crossOver(const Mat& parent1, const Mat& parent2, Mat& child1, Mat& child2)
	//{
	//	int random = rand() % parent1.cols;
	//	child1 = Mat_<int>(1,parent1.cols);
	//	child2 = Mat_<int>(1,parent1.cols);

	//	for (int i = 0; i < random; i++)
	//	{
	//		child1.at<int>(0,i) = parent1.at<int>(0,i);
	//		child2.at<int>(0,i) = parent2.at<int>(0,i);
	//	}
	//	for (int i = random; i < parent1.cols; i++)
	//	{
	//		child2.at<int>(0,i) = parent1.at<int>(0,i);
	//		child1.at<int>(0,i) = parent2.at<int>(0,i);
	//	}
	//}

	//static int countNumberOfAttributes(Mat d)
	//{
	//	int cnt = 0;
	//	for (int i = 0; i < d.cols; i++)
	//	{
	//		if (d.at<int>(0,i) == 1)
	//		{
	//			cnt++;
	//		}
	//	}
	//	return cnt;
	//}

	//static float getROCevaluation(const Mat& d, const Mat& l, CvSVM classifier, CvSVMParams params, int k)
	//{
	//	//Mat conf = conf_matrix<Classifier, Params>(classifier, params, d, l, k);
	//	//cout << conf << endl;
	//	//float temp = ROC(conf);
	//	//conf.f
	//	return ROC(conf_matrix(classifier, params, d, l, k));
	//}

	//static Mat conf_matrix(CvSVM c, CvSVMParams p, const Mat& data, const Mat& label, int k)
	//{
	//	Mat conf = Mat::zeros(2,2, CV_32S);
	//	int testNum = (data.rows / k);
	//	int init = 0;
	//	int final = testNum;;

	//	float accuracy = 0;
	//	for (int i = 0; i < k; i++)
	//	{
	//		int cntTrain = 0;
	//		int cntTest = 0;
	//		Mat_<float> test(testNum, data.cols);
	//		Mat_<float> train(data.rows - testNum, data.cols);
	//		Mat_<float> testLabels(testNum, 1);
	//		Mat_<float> trainLabels(data.rows - testNum, 1);
	//		for (int n = 0; n < data.rows; n++)
	//		{
	//			Mat tempData = data.row(n) + 0;
	//			int tempLabel = label.at<float>(n,0);
	//			if (n >= init && n < final )
	//			{
	//				test.row(cntTest) = data.row(n) + 0;
	//				testLabels.at<float>(cntTest,0) = tempLabel;
	//				cntTest++;
	//			}
	//			else
	//			{

	//				train.row(cntTrain) = data.row(n) + 0;
	//				trainLabels.at<float>(cntTrain,0) = tempLabel;
	//				cntTrain++;
	//			}
	//		}
	//		init = init + testNum;
	//		final = final + testNum;

	//		c.train(train, trainLabels, Mat(), Mat(), p);

	//		Mat_<float> predicted(testLabels.rows, 1);

	//		for(int n = 0; n < test.rows; n++)
	//		{
	//			Mat sample = test.row(n);
	//			float result = c.predict(sample);
	//			predicted.at<float>(n, 0) = result;
	//		}

	//		for(int i = 0; i < testLabels.rows; i++)
	//		{
	//			float p = predicted.at<float>(i,0);
	//			float a = testLabels.at<float>(i,0);

	//			//conf.at<int>(static_cast<int>(a),static_cast<int>(p))++;

	//			if ( fabs(p-a) < FLT_EPSILON && a == 1)
	//			{
	//				int temp = conf.at<int>(0,0);
	//				conf.at<int>(0,0) = temp + 1;
	//			}
	//			else if ( fabs(p-a) >= FLT_EPSILON && a == 0)
	//			{
	//				int temp = conf.at<int>(0,1);
	//				conf.at<int>(0,1) = temp + 1;
	//			}
	//			else if ( fabs(p-a) >= FLT_EPSILON && a == 1)
	//			{
	//				int temp = conf.at<int>(1,0);
	//				conf.at<int>(1,0) = temp + 1;
	//			}
	//			else if ( fabs(p-a) < FLT_EPSILON && a == 0)
	//			{
	//				int temp = conf.at<int>(1,1);
	//				conf.at<int>(1,1) = temp + 1;
	//			}
	//		}
	//	}
	//	//cout << conf << endl;
	//	return conf;
	//}